import { Injectable } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { RedisService } from 'src/modules/common/services/redis.service';
import { MatchInfo } from './entities/match.entity';
import { MatchService } from './match.service';

@Injectable()
export class MatchCacheService {
  constructor(
    private readonly redisService: RedisService,
    private readonly matchService: MatchService,
  ) {}
  private getListByStageIdKey = 'match:getListByStageId';
  private getSimpleMatchByIdKey = 'match:getSimpleMatch';

  @OnEvent('match.update')
  async handleMatchUpdate(payload: MatchInfo) {
    await this.deleteMatch(payload.id);
    const { stageId, tournamentId } = payload;
    await this.deleteListByStageId(stageId);
    await this.deleteListByTournamentId(tournamentId);
  }

  async getMatch(matchId: number) {
    const res = await this.redisService.get(
      `${this.getSimpleMatchByIdKey}:${matchId}`,
    );
    if (!res) {
      const match = await this.matchService.findOneById(matchId);
      await this.setMatch(match);
      return match;
    } else {
      return JSON.parse(res);
    }
  }

  async setMatch(match: MatchInfo) {
    await this.redisService.set(
      `${this.getSimpleMatchByIdKey}:${match.id}`,
      JSON.stringify(match),
    );
  }

  async deleteMatch(matchId: number) {
    await this.redisService.delete(`${this.getSimpleMatchByIdKey}:${matchId}`);
  }

  async getListByStageId(stageId: number) {
    const res = await this.redisService.get(
      `${this.getListByStageIdKey}:${stageId}`,
    );
    return res ? JSON.parse(res) : null;
  }

  async setListByStageId(stageId: number, list: MatchInfo[]) {
    await this.redisService.set(
      `${this.getListByStageIdKey}:${stageId}`,
      JSON.stringify(list),
    );
  }

  async deleteListByStageId(stageId: number) {
    await this.redisService.delete(`${this.getListByStageIdKey}:${stageId}`);
  }

  async getListByTournamentId(tournamentId: number) {
    const res = await this.redisService.get(
      `match:getListByTournamentId:${tournamentId}`,
    );
    if (!res) {
      const list =
        await this.matchService.getMatchesByTournamentId(tournamentId);
      await this.setListByTournamentId(tournamentId, list);
      return list;
    }
    return res ? JSON.parse(res) : null;
  }

  async setListByTournamentId(tournamentId: number, list: MatchInfo[]) {
    await this.redisService.set(
      `match:getListByTournamentId:${tournamentId}`,
      JSON.stringify(list),
    );
  }

  async deleteListByTournamentId(tournamentId: number) {
    await this.redisService.delete(
      `match:getListByTournamentId:${tournamentId}`,
    );
  }
}
